/*Copyright ©2017 TommyLemon(https://github.com/TommyLemon/APIJSONAuto)

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use JSONResponse file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.*/


/**parser for json response
 * @author Lemon
 */

//状态信息，非GET请求获得的信息<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

var CODE_SUCCESS = 200; //成功
var CODE_UNSUPPORTED_ENCODING = 400; //编码错误
var CODE_ILLEGAL_ACCESS = 401; //权限错误
var CODE_UNSUPPORTED_OPERATION = 403; //禁止操作
var CODE_NOT_FOUND = 404; //未找到
var CODE_ILLEGAL_ARGUMENT = 406; //参数错误
var CODE_NOT_LOGGED_IN = 407; //未登录
var CODE_TIME_OUT = 408; //超时
var CODE_CONFLICT = 409; //重复，已存在
var CODE_CONDITION_ERROR = 412; //条件错误，如密码错误
var CODE_UNSUPPORTED_TYPE = 415; //类型错误
var CODE_OUT_OF_RANGE = 416; //超出范围
var CODE_NULL_POINTER = 417; //对象为空
var CODE_SERVER_ERROR = 500; //服务器内部错误


var MSG_SUCCEED = "success"; //成功
var MSG_SERVER_ERROR = "Internal Server Error!"; //服务器内部错误


var KEY_CODE = "code";
var KEY_MSG = "msg";
var KEY_ID = "id";
var KEY_ID_IN = KEY_ID + "{}";
var KEY_COUNT = "count";
var KEY_TOTAL = "total";

var TAG = 'JSONResponse';

function compareFromJava(target, real, folder, isMachineLearning) {
	return JSON.stringify(compareResponse(JSON.parse(target), JSON.parse(real), folder, isMachineLearning));
}
function updateStandardFromJava(target, real) {
	return JSON.stringify(updateStandard(JSON.parse(target), JSON.parse(real)));
}

/**是否成功
 * @param code
 * @return
 */
function isSuccess(code) {
	return code == CODE_SUCCESS;
}

/**校验服务端是否存在table
 * @param count
 * @return
 */
function isExist(count) {
	return count > 0;
}



/**格式化key名称
 * @param object
 * @return
 */
function formatObject(object) {
	//太长查看不方便，不如debug	 log(TAG, "format  object = \n" + JSON.toJSONString(object));
	if (object == null || object == '') {
		log(TAG, "format  object == null || object == '' >> return object;");
		return object;
	}
	var formattedObject = {};

	var value;
	for (var key in object) {
		value = object[key];

		if (value instanceof Array) { // JSONArray，遍历来format内部项
			formattedObject[replaceArray(key)] = formatArray(value);
		}
		else if (value instanceof Object) { // JSONObject，往下一级提取
			formattedObject[getSimpleName(key)] = formatObject(value);
		}
		else { // 其它Object，直接填充
			formattedObject[getSimpleName(key)] = value;
		}
	}

	//太长查看不方便，不如debug	 log(TAG, "format  return formattedObject = " + JSON.toJSONString(formattedObject));
	return formattedObject;
}

/**格式化key名称
 * @param array
 * @return
 */
function formatArray(array) {
	//太长查看不方便，不如debug	 log(TAG, "format  array = \n" + JSON.toJSONString(array));
	if (array == null || array == '') {
		log(TAG, "format  array == null || array == '' >> return array;");
		return array;
	}
	var formattedArray = [];

	var value;
	for (var i = 0; i < array.length; i++) {
		value = array[i];
		if (value instanceof Array) { // JSONArray，遍历来format内部项
			formattedArray.push(formatArray(value));
		}
		else if (value instanceof Object) { // JSONObject，往下一级提取
			formattedArray.push(formatObject(value));
		}
		else { // 其它Object，直接填充
			formattedArray.push(value);
		}
	}

	//太长查看不方便，不如debug	 log(TAG, "format  return formattedArray = " + JSON.toJSONString(formattedArray));
	return formattedArray;
}

/**替换key+KEY_ARRAY为keyList
 * @param key
 * @return getSimpleName(isArrayKey(key) ? getArrayKey(...) : key) {@link #getSimpleName(String)}
 */
function replaceArray(key) {
	if (JSONObject.isArrayKey(key)) {
		key = getArrayKey(key.substring(0, key.lastIndexOf('[]')));
	}
	return getSimpleName(key);
}
/**获取列表变量名
 * @param key => getNoBlankString(key)
 * @return empty ? "list" : key + "List" 且首字母小写
 */
function getArrayKey(key) {
	return StringUtil.addSuffix(key, "List");
}

/**获取简单名称
 * @param fullName name 或 name:alias
 * @return name => name; name:alias => alias
 */
function getTableName(fullName) {
	//key:alias  -> alias; key:alias[] -> alias[]
	var index = fullName == null ? -1 : fullName.indexOf(":");
	return index < 0 ? fullName : fullName.substring(0, index);
}

/**获取简单名称
 * @param fullName name 或 name:alias 或 User-name 或 User-name:alias
 * @return name => name; name:alias 或 User-name:alias => alias; User-name => userName
 */
function getSimpleName(fullName) {
	//key:alias -> alias
	var index = fullName == null ? -1 : fullName.indexOf(":");
	if (index >= 0) {
		return fullName.substring(index + 1);
	}

	var left = index < 0 ? fullName : fullName.substring(0, index);

	var first = true;
	var name = '';
	var part;
	do {
		index = left.indexOf("-");
		part = index < 0 ? left : left.substring(0, index);

		name += StringUtil.firstCase(part, ! first);
		left = left.substring(index + 1);

		first = false;
	}
	while (index >=0);

	return name;
}



var COMPARE_NO_STANDARD = -1;
var COMPARE_EQUAL = 0;
var COMPARE_KEY_MORE = 1;
var COMPARE_LENGTH_CHANGE = 2;
var COMPARE_VALUE_CHANGE = 2;
var COMPARE_KEY_LESS = 3;
var COMPARE_TYPE_CHANGE = 4;
var COMPARE_NUMBER_TYPE_CHANGE = 3;
var COMPARE_CODE_CHANGE = 4;

/**测试compare: 对比 新的请求与上次请求的结果
   0-相同，无颜色；
   1-对象新增字段或数组新增值，绿色；
   2-值改变，蓝色；
   3-对象缺少字段/整数变小数，黄色；
   4-code/值类型 改变，红色；
 */
function compareResponse(target, real, folder, isMachineLearning) {
	if (target == null || target.code == null) {
		return {
			code: COMPARE_NO_STANDARD, //未上传对比标准
			msg: '没有校验标准！',
			path: folder == null ? '' : folder
		};
	}
	if (target.code != real.code) {
		return {
			code: COMPARE_CODE_CHANGE,
			msg: '状态码改变！',
			path: folder == null ? '' : folder
		};
	}

	var tCode = target.code;
	var rCode = real.code;

	delete target.code;
	delete real.code;

	//可能提示语变化，也要提示
	// delete target.msg;
	// delete real.msg;

	var result = isMachineLearning == true ? compareWithStandard(target, real, folder) : compareWithBefore(target, real, folder);

	target.code = tCode;
	real.code = rCode;

	return result;
}

/**测试compare: 对比 新的请求与上次请求的结果
   0-相同，无颜色；
   1-新增字段/新增值，绿色；
   2-值改变，蓝色；
   3-缺少字段/整数变小数，黄色；
   4-类型/code 改变，红色；
 */
function compareWithBefore(target, real, folder) {
	folder = folder == null ? '' : folder;

	if (target == null) {
		return {
			code: real == null ? COMPARE_EQUAL : COMPARE_KEY_MORE,
					msg: real == null ? '结果正确' : '是新增的',
							path: real == null ? '' : folder,
									value: real
		};
	}
	if (real == null) { //少了key
		return {
			code: COMPARE_KEY_LESS,
			msg: '是缺少的',
			path: folder,
			value: real
		};
	}

	var type = typeof target;
	if (type != typeof real) { //类型改变
		return {
			code: COMPARE_TYPE_CHANGE,
			msg: '值改变',
			path: folder,
			value: real
		};
	}

	// var max = COMPARE_EQUAL;
	// var each = COMPARE_EQUAL;

	var max = {
			code: COMPARE_EQUAL,
			msg: '结果正确',
			path: '', //导致正确时也显示 folder,
			value: null //导致正确时也显示  real
	};

	var each;

	if (target instanceof Array) { // JSONArray
		var all = target[0];
		for (var i = 1; i < length; i++) { //合并所有子项, Java类型是稳定的，不会出现两个子项间同名字段对应值类型不一样
			all = deepMerge(all, target[i]);
		}
		//下载需要看源JSON  real = [all];

		each = compareWithBefore(target[0], all, getAbstractPath(folder, i));

		if (max.code < each.code) {
			max = each;
		}

		if (max.code < COMPARE_VALUE_CHANGE) {
			if (target.length != real.length || (JSON.stringify(target) != JSON.stringify(real))) {
				max.code = COMPARE_VALUE_CHANGE;
				max.msg = '值改变';
				max.path = folder;
				max.value = real;
			}
		}
	}
	else if (target instanceof Object) { // JSONObject
		var tks = Object.keys(target);
		var key;
		for (var i = 0; i < tks.length; i++) { //遍历并递归下一层
			key = tks[i];
			if (key == null) {
				continue;
			}

			each = compareWithBefore(target[key], real[key], getAbstractPath(folder, key));
			if (max.code < each.code) {
				max = each;
			}
			if (max.code >= COMPARE_TYPE_CHANGE) {
				break;
			}
		}


		if (max.code < COMPARE_KEY_MORE) { //多出key
			for (var k in real) {
				if (k != null && tks.indexOf(k) < 0) {
					max.code = COMPARE_KEY_MORE;
					max.msg = '是新增的';
					max.path = getAbstractPath(folder,  k);
					max.value = real[k];
					break;
				}
			}
		}
	}
	else { // Boolean, Number, String
		if (type == 'number') { //数字类型由整数变为小数
			if (String(target).indexOf('.') < 0 && String(real).indexOf('.') >= 0) {
				max.code = COMPARE_NUMBER_TYPE_CHANGE;
				max.msg = '整数变小数';
				max.path = folder;
				max.value = real;
			}
		}

		if (max.code < COMPARE_VALUE_CHANGE && target !== real) { //值不同
			max.code = COMPARE_VALUE_CHANGE;
			max.msg = '值改变';
			max.path = folder;
			max.value = real;
		}
	}

	return max;
}

function deepMerge(left, right) {
	if (left == null) {
		return right;
	}
	if (right == null) {
		return left;
	}

	if (right instanceof Array) {
		var lfirst = left[0];
		if (lfirst instanceof Object) {
			for (var i = 1; i < left.length; i++) {
				lfirst = deepMerge(lfirst, left[i]);
			}
		}

		var rfirst = right[0];
		if (rfirst instanceof Object) {
			for (var i = 1; i < right.length; i++) {
				rfirst = deepMerge(rfirst, right[i]);
			}
		}

		var m = deepMerge(lfirst, rfirst);

		return m == null ? [] : [ m ];
	}

	if (right instanceof Object) {
		var m = JSON.parse(JSON.stringify(left));
		for (var k in right) {
			m[k] = deepMerge(m[k], right[k]);
		}
		return m;
	}

	return left;
}



/**测试compare: 对比 新的请求与上次请求的结果
   0-相同，无颜色；
   1-新增字段/新增值，绿色；
   2-值改变，蓝色；
   3-缺少字段/整数变小数，黄色；
   4-类型/code 改变，红色；
 */
function compareWithStandard(target, real, folder) {
	folder = folder == null ? '' : folder;

	if (target == null) {
		return {
			code: COMPARE_NO_STANDARD,
			msg: '没有校验标准！',
			path: folder,
			value: real
		};
	}
	if (target instanceof Array) { // JSONArray
		throw new Error('Standard 在 ' + folder + ' 语法错误，不应该有 array！');
	}

	log('\n\n\n\n\ncompareWithStandard <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n' +
			' \ntarget = ' + JSON.stringify(target, null, '    ') + '\n\n\nreal = ' + JSON.stringify(real, null, '    '));

	var notnull = target.notnull;
	log('compareWithStandard  notnull = target.notnull = ' + notnull + ' >>');

	var type = target.type;
	log('compareWithStandard  type = target.type = ' + type + ' >>');

	var valueLevel = target.valueLevel;
	log('compareWithStandard  valueLevel = target.valueLevel = ' + valueLevel + ' >>');

	var values = target.values;
	log('compareWithStandard  values = target.values = ' + JSON.stringify(values, null, '    ') + ' >>');

	if ((values == null || values[0] == null) && (type == 'object' || type == 'array')) {
		if (notnull == true) { // values{} values&{}
			throw new Error('Standard 在 ' + folder + ' 语法错误，Object 或 Array 在 notnull: true 时 values 必须为有值的数组 !');
		}

		log('compareWithStandard  values == null; real ' + (real == null ? '=' : '!') + '= null >> return ' + (real == null ? 'COMPARE_EQUAL' : 'COMPARE_KEY_MORE'));
		return {
			code: real == null ? COMPARE_EQUAL : COMPARE_KEY_MORE,
					msg: real == null ? '结果正确' : '是新增的',
							path: real == null ? '' : folder,
									value: real
		};
	}

	if (real == null) { //少了key
		log('compareWithStandard  real == null >> return ' + (notnull == true ? 'COMPARE_KEY_LESS' : 'COMPARE_EQUAL'));
		return {
			code: notnull == true ? COMPARE_KEY_LESS : COMPARE_EQUAL,
					msg: notnull == true ? '是缺少的' : '结果正确',
							path: notnull == true ? folder : '',
									value: real
		};
	}



	if (type != getType(real)) { //类型改变
		log('compareWithStandard  type != getType(real) >> return COMPARE_TYPE_CHANGE');
		return {
			code: COMPARE_TYPE_CHANGE,
			msg: '不是 ' + type + ' 类型',
			path: folder,
			value: real
		};
	}

	var max = {
			code: COMPARE_EQUAL,
			msg: '结果正确',
			path: '', //导致正确时也显示 folder,
			value: null //导致正确时也显示  real
	};

	var each;

	if (type == 'array') { // JSONArray
		log('compareWithStandard  type == array >> ');

		for (var i = 0; i < real.length; i ++) { //检查real的每一项
			log('compareWithStandard  for i = ' + i + ' >> ');

			each = compareWithStandard(values[0], real[i], getAbstractPath(folder, i));

			if (max.code < each.code) {
				max = each;
			}
			if (max.code >= COMPARE_TYPE_CHANGE) {
				log('compareWithStandard  max >= COMPARE_TYPE_CHANGE >> return max = ' + max);
				return max;
			}
		}

		if (max.code < COMPARE_LENGTH_CHANGE
				&& isValueCorrect(target.lengthLevel, target.lengths, real.length) != true) {
			max.code = COMPARE_LENGTH_CHANGE;
			max.msg = '长度超出范围';
			max.path = folder;
			max.value = real.length;
		}
	}
	else if (type == 'object') { // JSONObject
		log('compareWithStandard  type == object >> ');

		var tks = values == null ? [] : Object.keys(values[0]);
		var tk;
		for (var i = 0; i < tks.length; i++) { //遍历并递归下一层
			tk = tks[i];
			if (tk == null) {
				continue;
			}
			log('compareWithStandard  for tk = ' + tk + ' >> ');

			each = compareWithStandard(values[0][tk], real[tk], getAbstractPath(folder,  tk));
			if (max.code < each.code) {
				max = each;
			}
			if (max.code >= COMPARE_TYPE_CHANGE) {
				log('compareWithStandard  max >= COMPARE_TYPE_CHANGE >> return max = ' + max);
				return max;
			}
		}


		if (max.code < COMPARE_KEY_MORE) { //多出key
			log('compareWithStandard  max < COMPARE_KEY_MORE >> ');

			for (var k in real) {
				log('compareWithStandard  for k = ' + k + ' >> ');

				if (k != null && tks.indexOf(k) < 0) {
					log('compareWithStandard  k != null && tks.indexOf(k) < 0 >> max = COMPARE_KEY_MORE;');

					max.code = COMPARE_KEY_MORE;
					max.msg = '是新增的';
					max.path = getAbstractPath(folder,  k);
					max.value = real[k];
					break;
				}
			}
		}

	}
	else { // Boolean, Number, String
		log('compareWithStandard  type == boolean | number | string >> ');

		if (max.code < COMPARE_VALUE_CHANGE
				&& isValueCorrect(valueLevel, values, real) != true) {
			max.code = COMPARE_VALUE_CHANGE;
			max.msg = '值超出范围';
			max.path = folder;
			max.value = real;
		}

		if (max.code < COMPARE_LENGTH_CHANGE) {
			log('compareWithStandard  max < COMPARE_LENGTH_CHANGE >> ');

			var realLength = getLength(real);
			log('compareWithStandard  realLength = ' + realLength + ' >> ');

			if (realLength != null
					&& isValueCorrect(target.lengthLevel, target.lengths, realLength) != true) {
				max.code = COMPARE_LENGTH_CHANGE;
				max.msg = '长度超出范围';
				max.path = folder;
				max.value = realLength;
			}
		}
	}

	log('\ncompareWithStandard >> return max = ' + max + '\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n\n\n\n\n');
	return max;
}

function getAbstractPath (folder, name) {
	folder = folder == null ? '' : folder;
	name = name == null ? '' : name; //导致 0 变为 ''   name = name || '';
	return StringUtil.isEmpty(folder, true) ? name : folder + '/' + name;
}

function isValueCorrect (level, target, real) {
	log('isValueCorrect  \nlevel = ' + level + '; \ntarget = ' + JSON.stringify(target)
			+ '\nreal = ' + JSON.stringify(real, null, '    '));
	if (target == null) {
		log('isValueCorrect  target == null >>  return true;');
		return true;
	}
	if (level == null) {
		level = 0;
	}

	if (level == 0) {
		if (target.indexOf(real) < 0) { // 'key{}': [0, 1]
			log('isValueCorrect  target.indexOf(real) < 0 >>  return false;');
			return false;
		}
	}
	else if (level == 1) { //real <= max; real >= min
		if (target[0] != null && target[0] < real) {
			log('isValueCorrect  target[0] != null && target[0] < real >>  return false;');
			return false;
		}
		if (target.length > 1 && target[target.length - 1] != null && target[target.length - 1] > real) {
			log('isValueCorrect  target.length > 1 && target[target.length - 1] != null && target[target.length - 1] > real >>  return false;');
			return false;
		}
	}
	else if (level == 2) {
		for (var i = 0; i < target.length; i ++) {

			if (eval(real + target[i]) != true) {
				log('isValueCorrect  eval(' + (real + target[i]) + ') != true >>  return false;');
				return false;
			}
		}
	}
	else {
		//不限
	}

	log('isValueCorrect >> return true;');
	return true;
}

function getType (o) { //typeof [] = 'object'
	log('getType  o = ' + JSON.stringify(o) + '>> return ' + (o instanceof Array ? 'array' : typeof o));

	return o instanceof Array ? 'array' : typeof o;
}


/**更新测试标准，通过原来的标准与最新的数据合并来实现
 */
function updateStandard(target, real) {
	if (target instanceof Array) { // JSONArray
		throw new Error("Standard 语法错误，不应该有 array！");
	}
	if (real == null) { //少了key
		log('updateStandard  real == null');
		if (target != null) { //} && target.values != null && target.values[0] != null) {
			log('updateStandard  target != null >> target.notnull = false;');
			target.notnull = false;
		}
		log('updateStandard  return target;');
		return target;
	}

	if (target == null) {
		target = {};
	}

	log('\n\n\n\n\nupdateStandard <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n' +
			' \ntarget = ' + JSON.stringify(target, null, '    ') + '\n\n\nreal = ' + JSON.stringify(real, null, '    '));

	var notnull = target.notnull;
	log('updateStandard  notnull = target.notnull = ' + notnull + ' >>');
	if (notnull == null) {
		notnull = target.notnull = true;
	}

	var type = target.type;
	log('updateStandard  type = target.type = ' + type + ' >>');
	// if (type == null) { //强制用real的类型替代
	type = target.type = getType(real);
	// }
	log('updateStandard  type = target.type = getType(real) = ' + type + ' >>');


	var lengthLevel = target.lengthLevel;
	var lengths = target.lengths;
	log('updateStandard  lengthLevel = target.lengthLevel = ' + lengthLevel + ' >>');
	log('updateStandard  lengths = target.lengths = ' + lengths + ' >>');


	var valueLevel = target.valueLevel;
	var values = target.values;
	log('updateStandard  valueLevel = target.valueLevel = ' + valueLevel + ' >>');
	log('updateStandard  values = target.values = ' + JSON.stringify(values, null, '    ') + ' >>');

	if (valueLevel == null) {
		log('updateStandard  valueLevel == null >> valueLevel = target.valueLevel = 0;');
		valueLevel = target.valueLevel = 0;
	}


	if (type == 'array') {
		log('updateStandard  type == array >> ');

		if (values == null) {
			values = [];
		}
		if (values[0] == null) {
			values[0] = {};
		}

		var child = values[0];
		for (var i = 0; i < real.length; i ++) {
			log('updateStandard for i = ' + i + '; child = '
					+ JSON.stringify(child, null, '    ') + ';\n real[i] = '  + JSON.stringify(real[i], null, '    ') + ' >>');

			child = updateStandard(child, real[i]);
		}
		if (child == null) {
			log('updateStandard  child == null >> child = {}');
			child = {} //啥都确定不了，level为null默认用0替代
		}

		values = [child];
		target = setValue(target, real.length, lengthLevel == null ? 1 : lengthLevel, lengths, true);
		target = setValue(target, null, valueLevel, values, false);
	}
	else if (type == 'object') {
		log('updateStandard  type == object >> ');

		target.valueLevel = valueLevel;

		if (values == null) {
			values = [];
		}
		if (values[0] == null) {
			values[0] = {};
		}

		var realKeys = Object.keys(real) || [];
		for(var k2 in values[0]) { //解决real不含k2时导致notnull不能变成false
			// log('updateStandard for k2 in values[0] = ' + k2 + ' >>');
			if (realKeys.indexOf(k2) < 0) {
				// log('updateStandard Object.keys(real).indexOf(k2) < 0 >> real[k2] = null;');
				real[k2] = null;
			}
		}

		for(var k in real) {
			log('updateStandard for k in real = ' + k + '; values[0][k] = '
					+ JSON.stringify(values[0][k], null, '    ') + ';\n real[k] = '  + JSON.stringify(real[k], null, '    ') + ' >>');
			values[0][k] = updateStandard(values[0][k], real[k]);
		}

		target.values = values;
	}
	else {
		log('updateStandard  type == other >> ');

		if (values == null) {
			values = [];
		}
		if (valueLevel < 1 && type == 'number' && String(real).indexOf('.') >= 0) { //double 1.23
			valueLevel = 1;
		}
		target.values = values;

		target = setValue(target, getLength(real), lengthLevel == null ? 1 : lengthLevel, lengths, true);
		target = setValue(target, real, valueLevel, values, false);
	}

	log('\nupdateStandard >> return target = ' + JSON.stringify(target, null, '    ') + '\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> \n\n\n\n\n');

	return target;
}


function getLength(value) {
	var type = getType(value);
	if (type == 'array') {
		log('getLength  type == array >> return value.length = ' + value.length);
		return value.length;
	}
	if (type == 'object') {
		log('getLength  type == object >> return null;');
		return null;
	}

	if (type == 'number') {
		log('getLength  type == number >> ');

		var rs = String(value);

		//Double 比较整数长度
		var index = rs.indexOf(".");
		if (index >= 0) {
			rs = rs.substring(0, index);
		}

		log('getLength >> return rs.length = ' + rs.length);
		return rs.length
	}

	if (type == 'string') {
		log('getLength  type == string >> return value.length = ' + value.length);
		return value.length
	}

	//Boolean 不需要比较长度
	log('getLength  type == other >> return null;');
	return null;
}

/**
 * @param target
 * @param value
 * @param lengthLevel 0 - [] , 1 - min-max, 2 - "conditions", 3 - 任何值都行
 * @param originLength
 * @return {*}
 */
function setValue(target, real, level, origin, isLength) {
	log('setValue  level = ' + level + '; isLength = ' + isLength
			+ ' ;\n target = ' + JSON.stringify(target, null, '    ')
			+ ' ;\n real = ' + JSON.stringify(real, null, '    ')
			+ ' ;\n origin = ' + JSON.stringify(origin, null, '    ')
			+  ' >> ');

	if (target == null) {
		target = {};
	}
	var type = target.type;
	log('setValue  type = target.type = ' + type + ' >> ');

	if (level == null) {
		level = 0;
	}
	if (isLength != true || (type == 'array' || type == 'number' || type == 'string')) {

		var levelName = isLength != true ? 'valueLevel' : 'lengthLevel';
		target[levelName] = level;
		if (level >= 3) { //无限
			return target;
		}
		//String 类型在 长度超过一定值 或 不是 常量名 时，改成 无限模型
		//不用 type 判断类型，这样可以保证 lengthType 不会自动升级
		if (typeof real == 'string' && (real.length > 20 || StringUtil.isName(real) != true)) {
			if (level != 2) { //自定义模型不受影响
				target[levelName] = 3;
			}
			return target;
		}

		var vals = [];

		if (level == 0 || level == 1) {
			if (origin == null) {
				origin = [];
			}
			if (real != null && origin.indexOf(real) < 0) {
				origin.push(real);
			}

			vals = origin;
		}
		else {
			if (real != null) {
				vals.push(real);
			}
		}

		vals = vals.sort(function (x, y) { //倒序排列，一般都是用最大长度(数据count，字符串长度等)
			if (x < y) {
				return 1;
			}
			if (x > y) {
				return -1;
			}
			return 0;
		})

		var name = isLength != true ? 'values' : 'lengths';
		log('setValue  name = ' + name + '; vals = ' + JSON.stringify(vals, null, '    ') + ' >> ');

		switch (level) {
		case 0:
		case 1:
			//当 离散区间模型 可取值超过最大数量时自动转为 连续区间模型
			var maxCount = getMaxValueCount(type);
			var extraCount = maxCount <= 0 ? 0 : vals.length - maxCount;
			if (extraCount > 0 && level < 1) {
				if (typeof real == 'boolean') { //boolean 的 true 和 false 都行，说明不限
					if (level != 2) { //自定义模型不受影响
						target[levelName] = 3;
					}
					return target;
				}

				target[levelName] = 1;
			}

			//从中间删除多余的值
			while (extraCount > 0) {
				vals.splice(Math.ceil(vals.length/2), 1);
				extraCount -= 1;
			}
			target[name] = vals;
			break;
		case 2: //自定义的复杂条件，一般是准确的，不会纠错
			// target[name] = (StringUtil.isEmpty(origin, true) ? '' : origin + ',')
			//   + ('<=' + vals[0] + (vals.length <= 1 ? '' : ',>=' + vals[vals.length - 1]));
			break
		}
	}

	return target;
}

function getMaxValueCount(type) {
	switch (type) {
	case 'boolean':
		return 2;
	case 'number':
		return 10;
	case 'string':
		return 10;
	}

	return 0;
}

function log(msg) {
	// console.log(msg);
}


/**util for string
 * @author Lemon
 */
var StringUtil = {
  TAG: 'StringUtil',

  /**获取string,为null则返回''
   * @param s
   * @return
   */
  get: function(s) {
    return s == null ? '' : s;
  },

  /**获取去掉前后空格后的string,为null则返回''
   * @param s
   * @return
   */
  trim: function(s) {
    return StringUtil.get(s).trim();
  },

  /**获取去掉所有空格后的string,为null则返回''
   * @param s
   * @return
   */
  noBlank: function(s) {
    return StringUtil.get(s).replace(/ /g, '');
  },

  /**判断字符是否为空
   * @param s
   * @param trim
   * @return
   */
  isEmpty: function(s, trim) {
    if (s == null) {
      return true;
    }
    if (trim) {
      s = s.trim();
    }
    if (s == '') {
      return true;
    }

    return false;
  },

  /**判断是否为代码名称，只能包含字母，数字或下划线
   * @param s
   * @return
   */
  isName: function(s) {
    return s != null && /^[0-9a-zA-Z_]+$/.test(s);
  },


  /**添加后缀
   * @param key
   * @param suffix
   * @return key + suffix，第一个字母小写
   */
  addSuffix: function(key, suffix) {
    key = StringUtil.noBlank(key);
    if (key == '') {
      return StringUtil.firstCase(suffix);
    }
    return StringUtil.firstCase(key) + StringUtil.firstCase(suffix, true);
  },

  /**首字母大写或小写
   * @param key
   * @param upper
   * @return
   */
  firstCase: function(key, upper) {
    key = StringUtil.get(key);
    if (key == '') {
      return '';
    }

    var first = key.substring(0, 1);
    key = (upper ? first.toUpperCase() : first.toLowerCase()) + key.substring(1, key.length);

    return key;
  },

  /**全部大写
   * @param s
   * @param trim
   * @return
   */
  toUpperCase: function(s, trim) {
    s = trim ? StringUtil.trim(s) : StringUtil.get(s);
    return s.toUpperCase();
  },
  /**全部小写
   * @param s
   * @return
   */
  toLowerCase: function(s, trim) {
    s = trim ? StringUtil.trim(s) : StringUtil.get(s);
    return s.toLowerCase();
  },

  split: function (s, separator) {
    if (s == null) {
      return null;
    }

    if (separator == null) {
      separator = ',';
    }

    if (s.indexOf(separator) < 0) {
      return [s];
    }

    return s.split(separator)
  }

}